<template>
  <div class="pb-3">
    <input
      v-if="tag !== 'textarea'"
      v-bind="$attrs"
      class="form-control"
      :class="{'is-invalid': formObj.error}"
      @blur="validateEmail"
      v-model="formObj.val"
    >
    <textarea
      v-else
      v-bind="$attrs"
      class="form-control"
      :class="{'is-invalid': formObj.error}"
      @blur="validateEmail"
      v-model="formObj.val"
    ></textarea>
    <span v-if="formObj.error" class="invalid-feedback">{{formObj.message}}</span>
  </div>
</template>

<script lang="ts">
import { defineComponent, onMounted, PropType, reactive, computed } from 'vue'
import { emitter } from './ValidateForm.vue'
const emailReg = /^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/
interface minOrMax {// min   max 的规则
  message: string;
  length: number;
}
interface RuleProp { // 规则数组的规则
  type: 'required' | 'email' | 'range' | 'repeat';
  message?: string;
  isRepeatFn?: () => boolean;
  min?: minOrMax;// 引用规则
  max?: minOrMax;// 引用规则
}
// interface formObjRule { // form表单值规则
//   val: string;
//   error: boolean;
//   message: string | undefined
// }
export type Rule = RuleProp[]
export type TagType = 'input' | 'textarea'
export default defineComponent({
  name: 'ValidateInput',
  props: {
    rule: {
      type: Array as PropType<Rule>
    },
    modelValue: String,
    tag: {
      type: String as PropType<TagType>,
      default: 'input'
    }
  },
  setup (props, context) {
    const formObj = reactive({
      val: computed({ // 使用计算属性来实现双向绑定
        get: () => props.modelValue || '', // get--》 随父组件v-model值更新，返回更新之后的值，渲染到input框中
        set: val => { context.emit('update:modelValue', val) } // set--> 在val值被更改时触发，发射现有的值，把input框里的值发射给父组件
      }),
      error: false,
      message: ''
    })

    const validateEmail = () => { // 失去焦点事件来验证格式
      if (props.rule) {
        const allPassed = props.rule.every(item => {
          let passed = true
          let emailNum = null
          formObj.message = item.message || ''
          switch (item.type) {
            case 'required':
              passed = (formObj.val.trim() !== '')
              break
            case 'email':
              passed = emailReg.test(formObj.val)
              break
            case 'range':
              if (formObj.val.indexOf('@') !== -1) {
                emailNum = formObj.val.split('@')[0]
                passed = (emailNum as string).length >= 3 && (emailNum as string).length <= 12
                break
              } else if (formObj.val.length < (item.min as minOrMax).length && formObj.val.indexOf('') !== -1) {
                passed = false
                formObj.message = item.min?.message || ''
                break
              } else if (formObj.val.length > (item.max as minOrMax).length && formObj.val.indexOf('') !== -1) {
                passed = false
                formObj.message = item.max?.message || ''
              }
              break
            case 'repeat':
              passed = item.isRepeatFn ? item.isRepeatFn() : true
              break
            default:
              break
          }

          return passed
        })

        formObj.error = !allPassed
        return allPassed // 返回出结果
      }
      return true // 没有值 直接返回结果
    }

    const clearVal = () => { //  清除
      formObj.val = ''
    }

    onMounted(() => {
      emitter.emit('form-item-created', validateEmail) // 向form-item-created监听事件发射函数
      emitter.emit('clear-input-value', clearVal)
    })

    return { formObj, validateEmail }
  }
})
</script>
